iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
SideProject30

用 Rails 打造你的電商網站系列 第 18

Day 18 商品建立要馬上看到

  • 分享至 

  • xImage
  •  

Turbo Stream 跟 Turbo Frame

之前我們有用 Turbo Frame,

讓新增商品的動作能在 index 頁面執行

加上 Turbo Stream

我們在表單最外面加上 div 並且放上 id 讓 Turbo Stream 知道要找哪個地方渲染

# app/views/admin/drinks/index.html.erb

<div id="drink_list">
  <% @drinks.each do |drink| %>
    <%= turbo_frame_tag "drink_#{drink.id}" do %>
      <div class="w-2/4 p-4 mb-8 text-white border-2 rounded-lg bg-slate-500">
        <div class="flex items-center mb-4 field">
          <%= drink.name %>
        </div>
          
        <div class="flex items-center mb-4 field">
          <%= drink.description %>
        </div>
      
        <div class="flex items-center field">
          <%= number_to_currency(drink.price, precious: 0) %>
        </div>

        <div class="flex items-center field">
          <%= link_to '編輯', edit_admin_drink_path(drink), class: 'bg-white rounded-lg text-slate-500 p-2 mr-4' %>
          <%= link_to '刪除', admin_drink_path(drink), data: { turbo_method: :delete, confirm: '確定要刪除嗎' }, class: 'bg-white rounded-lg text-slate-500 p-2' %>
        </div>
      </div>
    <% end %>
  <% end %>
</div>

加上 create.turbo_stream.erb

我們要直接在區塊上插入新增的資料,所以就用 prepend

prepend 後面要加兩個參數,

第一個參數是你要在哪個區塊插入,

第二個參數是你要插入什麼內容,

不過因為我們要插入的內容不是一個檔案,無法用 partial 的方式,我們先用個 block 來包它

# app/views/admin/drinks/create.turbo_stream.erb

<%= turbo_stream.prepend "drink_list" do %>
  <%= turbo_frame_tag "drink_#{@drink.id}" do %>
    <div class="w-2/4 p-4 mb-8 text-white border-2 rounded-lg bg-slate-500">
      <div class="flex items-center mb-4 field">
        <%= @drink.name %>
      </div>
      <div class="flex items-center mb-4 field">
        <%= @drink.description %>
      </div>
      <div class="flex items-center field">
        <%= number_to_currency(@drink.price, precious: 0) %>
      </div>
      <div class="flex items-center field">
        <%= link_to '編輯', edit_admin_drink_path(@drink), class: 'bg-white rounded-lg text-slate-500 p-2 mr-4' %>
        <%= link_to '刪除', admin_drink_path(@drink), data: { turbo_method: :delete, confirm: '確定要刪除嗎' }, class: 'bg-white rounded-lg text-slate-500 p-2' %>
      </div>
    </div>
  <% end %>
<% end %>

在 controller 加上 respond

跟前一篇一樣,我們要在 controller 加上要回應的動作及訊息

# app/controllers/admin/drinks_controller.rb

def create
  @drink = Drink.new(drink_params)

  if @drink.save
    Product.create(productable: @drink)
    respond_to do |format|
      format.html { redirect_to admin_drinks_path, notice: "商品建立成功" }
      format.turbo_stream
    end
  else 
    render :new, notice: "欄位請完整填寫", status: :unprocessable_entity
  end
end

基本上到這邊,我們所要的效果就完成了,不過我們還是把程式碼整理一下

Yes

整理程式碼

把 block 包成一個 partial

# app/views/admin/drinks/_drink.html.erb

<div class="w-2/4 p-4 mb-8 text-white border-2 rounded-lg bg-slate-500">
  <div class="flex items-center mb-4 field">
    <%= drink.name %>
  </div>
  <div class="flex items-center mb-4 field">
    <%= drink.description %>
  </div>
  <div class="flex items-center field">
    <%= number_to_currency(drink.price, precious: 0) %>
  </div>
  <div class="flex items-center field">
    <%= link_to '編輯', edit_admin_drink_path(drink), class: 'bg-white rounded-lg text-slate-500 p-2 mr-4' %>
    <%= link_to '刪除', admin_drink_path(drink), data: { turbo_method: :delete, confirm: '確定要刪除嗎' }, class: 'bg-white rounded-lg text-slate-500 p-2' %>
  </div>
</div>

將 index 區塊改以 partial 方式渲染

# app/views/admin/drinks/index.html.erb

<div id="drink_list">
  <% @drinks.each do |drink| %>
    <%= turbo_frame_tag "drink_#{drink.id}" do %>
      <%= render 'drink', drink: drink %>
    <% end %>
  <% end %>
</div>

修改 create.turbo_stream.erb 的 block 內容為 partial

# app/views/admin/drinks/create.turbo_stream.erb

<%= turbo_stream.prepend "drink_list", partial: 'admin/drinks/drink', locals: { drink: @drink } %>

但剛剛我們在測試的時候發現新增商品不會消失,

我們需要在 turbo_stream 檔案中跟他說新增商品後,新增商品區塊要變成什麼樣子

把新增商品區塊取代成原本的樣子

<%= turbo_stream.prepend "drink_list", partial: 'admin/drinks/drink', locals: { drink: @drink } %>

<%= turbo_stream.update 'new_drinks' do %>
  <%= link_to '新增飲品', new_admin_drink_path, data: {turbo_frame: 'new_drinks'} %>
<% end %>

這樣就完成囉

Yes

Turbo Frame 跟 Turbo Stream 的介紹就到這邊


上一篇
Day 17 賠錢貨就是要快點消失!
下一篇
Day 19 JS 套件路徑表
系列文
用 Rails 打造你的電商網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言